<!--
 * @description: 量算。以测距举例：空间量算是两点间直线距离，贴地量算是两点连线贴地面时的距离，当场景存在地形数据时，两者才有差别。
 * @Author: FengKongLi
 * @Date: 2022-08-08 10:23:19
 * @LastEditors: FengKongLi
 * @LastEditTime: 2022-08-08 16:08:23
-->
<template>
  <div class="container">
    <secen-view @already="already"></secen-view>
    <div id="toolbar" class="tool-bar">
      <div>
        <Select
          v-model="selOpt"
          style="width: 200px"
          @on-change="handlerOptionChange"
        >
          <Option
            v-for="item in optionList"
            :value="item.value"
            :key="item.value"
            >{{ item.label }}</Option
          >
        </Select>
      </div>
      <div class="loaction">
        <button id="flytoMountain" class="button" @click="flytoMountain">
          定位至山区
        </button>
      </div>
      <button
        type="button"
        id="distance"
        class="button"
        @click="handlerMeasure('distance')"
      >
        测距
      </button>
      <button
        type="button"
        id="area"
        class="button"
        @click="handlerMeasure('area')"
      >
        测面
      </button>
      <button
        type="button"
        id="height"
        class="button"
        @click="handlerMeasure('height')"
      >
        测高
      </button>
      <button type="button" id="clear" class="button" @click="handlerClear">
        清除
      </button>

      <div class="isoheight">
        <Checkbox v-model="isShowLine" @on-change="handlerIoslineChange"
          >等高线</Checkbox
        >
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Measure",
  data() {
    return {
      viewer: "",
      optionList: [
        {
          value: "空间量算",
          label: "空间量算",
        },
        {
          value: "贴地量算",
          label: "贴地量算",
        },
      ],
      selOpt: "空间量算",
      isShowLine: true,
      isoline: 0,
      lineHeight: 0,
      handlerDis: "",
      handlerArea: "",
      handlerHeigh: "",
      //   空间模式
      clampMode: 0,
      setHypFlag: 0,
      layers: 0,
    };
  },
  methods: {
    already(viewer) {
      this.viewer = viewer;
      this.viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
        url: "http://www.supermapol.com/realspace/services/3D-dxyx_ios2/rest/realspace/datas/DatasetDEM_1@sichuanTer",
        isSct: true, //地形服务源自SuperMap iServer发布时需设置isSct为true
      });
      //添加SuperMap iServer发布的影像服务
      this.viewer.imageryLayers.addImageryProvider(
        new Cesium.SuperMapImageryProvider({
          url: "http://www.supermapol.com/realspace/services/3D-dxyx_ios2/rest/realspace/datas/MosaicResult_2@IMAGE_1",
        })
      );
      this.initIosline();
      this.initMeasure();
    },
    handlerOptionChange(value) {
      // value 选中的值
      // console.log(value);
      if (value == "空间量算") {
        this.clampMode = 0;
        this.handlerDis.clampMode = 0;
        this.handlerArea.clampMode = 0;
      } else {
        this.clampMode = 1;
        this.handlerArea.clampMode = 1;
        this.handlerDis.clampMode = 1;
      }
    },
    // 返回值true|false
    handlerIoslineChange(value) {
      //   console.log(value);
    },
    flytoMountain() {
      this.viewer.scene.camera.setView({
        destination: new Cesium.Cartesian3(
          -1206939.1925299785,
          5337998.241228442,
          3286279.2424502545
        ),
        orientation: {
          heading: 1.4059101895600987,
          pitch: -0.20917672793046682,
          roll: 2.708944180085382e-13,
        },
      });
    },
    // 初始化等高线
    initIosline() {
      // HypsometricSetting 分层设色类。该类主要用于制定三维模型渲染显示方案。
      // 分层设色是地图可视化的常用方式，它通过一定的颜色变化次序或色调深浅来表达和区别三维数据的不同属性。
      this.isoline = new Cesium.HypsometricSetting();
      //   DisplayMode 获取或设置显示模式。
      // HypsometricSettingEnum 分层设色枚举类
      // LINE 显示轮廓线，枚举值：2
      this.isoline.DisplayMode = Cesium.HypsometricSettingEnum.DisplayMode.LINE;
      //   ColorTable 获取或设置颜色表
      let colorTable = new Cesium.ColorTable();
      this.isoline._lineColor = Cesium.Color.fromCssColorString("#ff7d00");
      this.isoline.ColorTable = colorTable;
      this.isoline.Opacity = 0.6;
      //   获取或设置最大可见值。
      this.isoline.MaxVisibleValue = -100;
      //   获取或设置最小可见值。
      this.isoline.MinVisibleValue = -100;
      this.layers = this.viewer.scene.layers.layerQueue;
      this.viewer.scene.globe.HypsometricSetting = {
        hypsometricSetting: this.isoline,
        // AnalysisRegionMode 分析范围模式
        // ARM_ALL 全部区域参与分析充，枚举值：1
        analysisMode: Cesium.HypsometricSettingEnum.AnalysisRegionMode.ARM_ALL,
      };
    },
    initMeasure() {
      let that = this;
      // 初始化测距
      // MeasureHandler 量测处理器类。 (指定用于量测的视图，量测的模式，几何对象的风格（贴地 ，贴对象）)
      this.handlerDis = new Cesium.MeasureHandler(
        this.viewer,
        Cesium.MeasureMode.Distance,
        this.clampMode
      );
      // 注册测距功能事件
      // measureEvt 量测事件，监听当前事件以获取测量结果。
      //  当量测模式为MeasureMode.Distance时，回调结果为{distance : distance}。 当量测模式为MeasureMode.Area时，回调结果为{area : area,positions : positions}。 当量测模式为MeasureMode.DVH时，回调结果为{distance : distance,verticalHeight : vHeight,horizontalDistance : hHeight}。
      this.handlerDis.measureEvt.addEventListener(function (result) {
        let dis = Number(result.distance);
        let distance =
          dis > 1000 ? (dis / 1000).toFixed(2) + "km" : dis.toFixed(2) + "m";
        that.handlerDis.disLabel.text = "距离:" + distance;
      });
      // activeEvt 激活事件，监听当前事件以获取处理器的状态。
      // addEventListener 注册一个回调函数以在事件引发时执行
      this.handlerDis.activeEvt.addEventListener(function (isActive) {
        if (isActive == true) {
          that.viewer.enableCursorStyle = false;
          that.viewer._element.style.cursor = "";
        } else {
          that.viewer.enableCursorStyle = true;
        }
      });

      //初始化测量面积
      this.handlerArea = new Cesium.MeasureHandler(
        this.viewer,
        Cesium.MeasureMode.Area,
        this.clampMode
      );
      this.handlerArea.measureEvt.addEventListener(function (result) {
        let mj = Number(result.area);
        let area =
          mj > 1000000
            ? (mj / 1000000).toFixed(2) + "km²"
            : mj.toFixed(2) + "㎡";
        that.handlerArea.areaLabel.text = "面积:" + area;
      });
      this.handlerArea.activeEvt.addEventListener(function (isActive) {
        if (isActive == true) {
          that.viewer.enableCursorStyle = false;
          that.viewer._element.style.cursor = "";
        } else {
          that.viewer.enableCursorStyle = true;
        }
      });
      //   初始化测高
      // DVH 空间距离、水平距离、垂直距离三分量量算模式（测高）。
      this.handlerHeight = new Cesium.MeasureHandler(
        this.viewer,
        Cesium.MeasureMode.DVH
      );
      this.handlerHeight.measureEvt.addEventListener(function (result) {
        let distance =
          result.distance > 1000
            ? (result.distance / 1000).toFixed(2) + "km"
            : result.distance + "m";
        let vHeight =
          result.verticalHeight > 1000
            ? (result.verticalHeight / 1000).toFixed(2) + "km"
            : result.verticalHeight + "m";
        let hDistance =
          result.horizontalDistance > 1000
            ? (result.horizontalDistance / 1000).toFixed(2) + "km"
            : result.horizontalDistance + "m";
        that.handlerHeight.disLabel.text = "空间距离:" + distance;
        that.handlerHeight.vLabel.text = "垂直高度:" + vHeight;
        that.handlerHeight.hLabel.text = "水平距离:" + hDistance;
        //实时等高线显示
        that.lineHeight = Number(result.endHeight);
        if (that.isShowLine) {
          that.updateContourLine(that.lineHeight);
        }
      });

      this.handlerHeight.activeEvt.addEventListener(function (isActive) {
        if (isActive == true) {
          that.viewer.enableCursorStyle = false;
          that.viewer._element.style.cursor = "";
        } else {
          that.viewer.enableCursorStyle = true;
        }
      });
    },
    handlerMeasure(key) {
      this.deactiveAll();
      switch (key) {
        case "distance":
          //   activate() 激活量测处理器。
          this.handlerDis && this.handlerDis.activate();
          break;
        case "area":
          this.handlerArea && this.handlerArea.activate();
          break;
        case "height":
          if (!this.setHypFlag) {
            this.setHypsometricSetting();
          }
          this.updateContourLine(-10000);
          this.deactiveAll();
          this.handlerHeight && this.handlerHeight.activate();
          break;

        default:
          break;
      }
    },
    handlerClear() {
      this.deactiveAll();
      //   clear()清除所有关于量测的要素。
      this.handlerDis && this.handlerDis.clear();
      this.handlerArea && this.handlerArea.clear();
      this.handlerHeight && this.handlerHeight.clear();
      // 清除等值线
      this.updateContourLine(-10000);
    },
    deactiveAll() {
      //deactivate() 关闭量测处理器。
      this.handlerDis && this.handlerDis.deactivate();
      this.handlerArea && this.handlerArea.deactivate();
      this.handlerHeight && this.handlerHeight.deactivate();
      this.lineHeight = -10000;
    },
    // 设置等值线
    updateContourLine(height) {
      this.viewer.scene.globe.HypsometricSetting.hypsometricSetting.MaxVisibleValue =
        height;
      this.viewer.scene.globe.HypsometricSetting.hypsometricSetting.MinVisibleValue =
        height;
      if (!this.setHypFlag) return;
      for (let i = 0; i < this.layers.length; i++) {
        if (this.layers[i].hypsometricSetting.hypsometricSetting) {
          this.layers[i].hypsometricSetting.hypsometricSetting.MaxVisibleValue =
            height;
          this.layers[i].hypsometricSetting.hypsometricSetting.MinVisibleValue =
            height;
        } else {
          this.setHypsometricSetting();
        }
      }
    },
    // 初始化设置图层等高线
    setHypsometricSetting() {
      for (let i = 0; i < this.layers.length; i++) {
        this.layers[i].hypsometricSetting = {
          hypsometricSetting: this.isoline,
          analysisMode:
            Cesium.HypsometricSettingEnum.AnalysisRegionMode.ARM_ALL,
        };
      }
      this.setHypFlag = true;
    },
  },
};
</script>
<style lang="scss" scoped>
.container {
  position: relative;
  .tool-bar {
    position: absolute;
    top: 1rem;
    background-color: rgba(38, 38, 38, 0.75);
    padding: 1rem;
    .loaction {
      margin: 1rem 0;
      .button {
        padding: 0.3rem;
      }
    }
    .button {
      margin-right: 1rem;
      padding: 0.3rem;
    }
    .button:nth-last-child(2) {
      margin-right: 0;
    }
    .isoheight {
      margin-top: 1rem;
      ::v-deep .ivu-checkbox-wrapper {
        color: white;
      }
    }
  }
}
</style>
